/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package contract

import (
	"github.com/golang/protobuf/proto"
	"hundsun.com/hsl/hschain/common/types"
	jvmComm "hundsun.com/hsl/hschain/contract/jvm/jvm.go/common"
	pbcom "hundsun.com/hsl/hschain/protos/common"
	"hundsun.com/hsl/hschain/store/db"
)

// StatusDB 合约状态存储对象
type StatusDB struct {
	get db.DatabaseGet
}

// NewContractStatusDB new ContractStatusDB
func NewContractStatusDB(get db.DatabaseGet) *StatusDB {
	return &StatusDB{get: get}
}

// GetContractStatus get ContractStatus
func (c *StatusDB) GetContractStatus(statusKey string, address string, statusType jvmComm.ContractStatusType) (*pbcom.ContractStatus, error) {
	if c.get == nil {
		return nil, types.ErrNotFound
	}
	v, err := c.get.Get(GenContractStatusKey(statusKey, address, statusType))
	if err != nil {
		return nil, err
	}
	ctStatus := &pbcom.ContractStatus{}
	err = proto.Unmarshal(v, ctStatus)
	if err != nil {
		return nil, err
	}
	return ctStatus, nil
}

// GetContractStats get ContractStats
func (c *StatusDB) GetContractStats(statuskeys []string, contractName string, statusType jvmComm.ContractStatusType) ([]*pbcom.ContractStatus, error) {
	if c.get == nil {
		return nil, types.ErrNotFound
	}
	keys := make([][]byte, len(statuskeys))
	for i, key := range statuskeys {
		keys[i] = GenContractStatusKey(key, contractName, statusType)
	}
	values, err := c.get.Gets(keys)
	if err != nil {
		return nil, err
	}
	var ctStats []*pbcom.ContractStatus
	for _, v := range values {
		ctStat := &pbcom.ContractStatus{}
		err = proto.Unmarshal(v, ctStat)
		if err != nil {
			continue
		}
		ctStats = append(ctStats, ctStat)
	}
	return ctStats, nil
}

// StatusKV from ContractStatus to kv
func StatusKV(ctStat *pbcom.ContractStatus, statusType jvmComm.ContractStatusType) (*pbcom.KeyValue, error) {
	kv := &pbcom.KeyValue{}
	kv.Key = GenContractStatusKey(ctStat.Key, ctStat.Address, statusType)
	v, err := proto.Marshal(ctStat)
	if err != nil {
		return nil, err
	}
	kv.Value = v
	return kv, nil
}

// GenContractStatusKey generate ContractStatus key
func GenContractStatusKey(contractName string, key string, statusType jvmComm.ContractStatusType) []byte {
	if statusType == jvmComm.ContractStatusTypeEsdao {
		return []byte(db.NamespaceContractDao + contractName + key)
	}
	return []byte(db.NamespaceContractStatus + contractName + key)
}
